package com.itisyue.fun.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

public class FileUtil {
    private static Logger log = LoggerFactory.getLogger(FileUtil.class);
    /**
     * 文件拆分
     * @param sourceFile  源文件
     * @param targetDir   目的文件夹
     * @param maxSize
     */
    public static List<String> getSplitFile(String sourceFile, String targetDir, Long maxSize,  String tmpFlag){
        List<String> fileList = new ArrayList<>();
        if (maxSize==null || maxSize <= 1L * 1024*1024){
            maxSize = 1L * 1024*1024;//1M
        }

        //预分配文件所占用的磁盘空间，在磁盘创建一个指定大小的文件，“r”表示只读，“rw”支持随机读写
        try {
            File file = new File(sourceFile);
            String fileName = file.getName();
            RandomAccessFile raf = new RandomAccessFile(file, "r");
            //计算文件大小
            long length = raf.length();
//            //计算文件切片后每一份文件的大小
//            long maxSize = length / count;
            long count  = length%maxSize ==0 ? length / maxSize : length / maxSize + 1;

            log.info("length={}, maxSize={}, count={}", length, maxSize, count);

            long offset = 0L;//定义初始文件的偏移量(读取进度)
            //开始切割文件
            for(long i = 0; i < count - 1; i++){ //count-1最后一份文件不处理
                //标记初始化
                long fbegin = offset;
                //分割第几份文件
                long fend = (i+1) * maxSize;
                //写入文件
                String targetFile = targetDir + "/" + fileName + "_" + String.format("%05d", i) + "." + tmpFlag;
                fileList.add(targetFile);
                offset = getWrite(sourceFile, targetFile, fbegin, fend);

                //log.info("i={}, fbegin={}, fend={}, offset={}", i, fbegin, fend, offset);
            }

            //剩余部分文件写入到最后一份(如果不能平平均分配的时候)
            if (length - offset > 0) {
                //写入文件
                String targetFile = targetDir + "/" + fileName + "_" + String.format("%05d", count-1) + "." + tmpFlag;
                fileList.add(targetFile);
                getWrite(sourceFile, targetFile, offset, length);
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return fileList;

    }

    /**
     * 指定文件每一份的边界，写入不同文件中
     * @param sourceFile 源文件
     * @param targetFile 目的文件
     * @param begin 开始指针的位置
     * @param end 结束指针的位置
     * @return long
     */
    public static long getWrite(String sourceFile, String targetFile, long begin, long end){

        long endPointer = 0L;
        try {
            //申明文件切割后的文件磁盘
            RandomAccessFile in = new RandomAccessFile(new File(sourceFile), "r");
            //定义一个可读，可写的文件并且后缀名为.tmp的二进制文件
            RandomAccessFile out = new RandomAccessFile(new File(targetFile), "rw");

            //申明具体每一文件的字节数组
            byte[] b = new byte[1024];
            int n = 0;
            //从指定位置读取文件字节流
            in.seek(begin);
            //判断文件流读取的边界
            while(in.getFilePointer() <= end && (n = in.read(b)) != -1){
                //从指定每一份文件的范围，写入不同的文件
                out.write(b, 0, n);
            }

            //定义当前读取文件的指针
            endPointer = in.getFilePointer();

            //关闭输入流
            in.close();
            //关闭输出流
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return endPointer;
    }
    /**
     * 文件合并
     * @param file 指定合并文件
     * @param tempFileList 分割后的文件名列表
     */
    public static void merge(String file, List<String> tempFileList) {
        RandomAccessFile raf = null;
        try {
            //申明随机读取文件RandomAccessFile
            raf = new RandomAccessFile(new File(file), "rw");
            //开始合并文件，对应切片的二进制文件
            for (int i = 0; i < tempFileList.size(); i++) {
                //读取切片文件
                RandomAccessFile reader = new RandomAccessFile(new File(tempFileList.get(i)), "r");
                byte[] b = new byte[1024];
                int n = 0;
                while ((n = reader.read(b)) != -1) {
                    raf.write(b, 0, n);//一边读，一边写
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void deleteFileList(List<String> fileList){

        for(String fileStr: fileList){
            try {
                File file = new File(fileStr);
                file.delete();
            }catch (Exception e){
            }
        }
    }


    public static void main(String[] args) {

        String file = "/Users/fangyue/Downloads/SW_DVD9_Win_Pro_11_22H2.5_64ARM_ChnSimp_Pro_Ent_EDU_N_MLF_X23-37724 2.ISO";

        //1.根据现有的文件编写文件编写文件切片工具类
        getSplitFile(file, "/Users/fangyue/appdata/test/baiduDiskTest", 4*1024*1024L, "tmp");

//        //2.写入到二进制临时文件
//        //  getSplitFile(file, count);
//        //3.根据实际的需求合并指定数量的文件
//        String tempFile = "F:\\java-study\\img\\img.jpg";
//        merge(file, tempFile, 5);
    }

    public static void main1(String[] args) {
        String s = "/Users/fangyue/appdata/test/baiduDiskTest/1.txt";
        File file = new File(s);
        System.out.println(file.getName());
        if (s.contains("/")) {
            String[] split = s.split("/");
            System.out.printf(split[split.length - 1]);
        }
    }
}
